package demo2

import (
	"strings"
	"fmt"
	"sync"
)
// 回顾 中介者设计模式，观察者设计模式，享元设计模式

// 中介者设计模式

type CDDriver struct{
	data string
}

func (c *CDDriver)ReadData(){
	fmt.Println("光驱")
	c.data = "music,image"
	GetMediatorInstace().Get(c)
}
// 做数据分发
type CPU struct{
	Sound string
	Vedio string
}

func (c *CPU)Process(data string){
	fmt.Println("程序开始读取光驱")
	sp := strings.Split(data,",")
	// 把数据给对应的管理元件
	c.Sound = sp[0]
	c.Vedio = sp[1]
	GetMediatorInstace().Get(c)
}

// 硬件开始工作
type SoundCard strcut{
	data string
}

func (s *SoundCard) Play(data string){
	// 声卡开始播放
	s.data = data
	GetMediatorInstace().Get(s)
}

type VedioCard struct{
	data string
}

func (v *VedioCard) Display(data string){
	// 显卡开始播放
	v.data = data 
	GetMediatorInstace().Get(v)

}

type mediator struct{
	// 电视机 包含
	cd 		*CDDriver
	cpu 	*CPU
	sound 	*SoundCard
	vedio 	*VedioCard
}
var mediator *mediator

func GetMediatorInstace() *mediator{
	if mediator == nil {
		mediator = &mediator{}
	}
	return mediator
}

func (m *mediator)Get(ins interface{}){
	switch inst := ins.(type) {
	case *CDDriver:
		m.cpu.Process()
	case *CPU:
		// 把数据给对应的硬件
		m.sound.Play(inst.data)
		m.vedio.Display(inst.data)
	}
}

// 观察者设计模式

type Observer interface{
	Update(Subject)
}

// 发布者
type Subject struct{
	contxt 		string
	observers 	[]Observice // 订阅者
}

func (s *Subject)Attch(o Observer){
	s.observers = append(s.observers,o)
}

func (s *Subject) notify(){
	for _,o := range s.observers{
		o.Update(s)
	}
}

func (s *Subject) Contxt(filename string){
	s.contxt = filename
	// 只要发布数据，立刻 更新订阅者的内容，作用场景触发连，但是订阅者不能太多，性能消耗较大
	s.notify()
}

type Observice struct{
	name string
}

func NewObservice(name string) *Observice{
	return &Observice{
		name:name,
	}
}

func (o *Observice)Update(s *Subject){
	fmt.Println(o.name + "接受到数据:"  + s.contxt)
}

// 享元设计模式
//  比如说有一个U盘里面放了很多镜像文件，每一个镜像文件都能做一个系统，就不用每次的找不同的u盘里面安装不同的镜像文件了
// 减少内存的开辟，空间的占用，节约时间
// 类似服务的注册和发现，或者建立的链接数不够的前提先然后获取新的链接
// 运用场景在上下文，中间件里

// 定义u盘
type ImageFlyweightFactory struct{
	maps map[string]*ImageFlyweight
}

// 构造方法
var imageFlyweightFactory *ImageFlyweightFactory

// 单利模式
func NewImageFlayweightFactory()*ImageFlyweightFactory{
	if imageFlyweightFactory ==nil{
		imageFlyweightFactory = &ImageFlyweightFactory{
			maps:make(map[string]*ImageFlyweight),
		}
	}
	return imageFlyweightFactory
}

// 获取u盘中某个镜像文件
func (i *ImageFlyweightFactory)GetImageFlyweight(filename string)*ImageFlyweight{
	image := i.maps[filename]
	if image == nil {
		// 如果没有镜像文件的话，就下载一个存到u盘里面
		i.maps[filename]= NewImageFlyweight()
	}
	return image
}

// 镜像文件
type ImageFlyweight struct{
	filename string
}
// 获取一个空的镜像文件/ 也可以传入不同的参数定制镜像文件
func NewImageFlyweight()*ImageFlyweight{
	return &ImageFlyweight{}
}

// 获取下载文件的详情
func (i *ImageFlyweight)Data() string{
	return i.filename
}
// 下载镜像文件
func (i *ImageFlyweight)Download(contxt string){
	i.filename = contxt
}

// 查看镜像文件的结果
type ImageViewer struct{
	*ImageFlyweight
}

func NewImageViewer(filename string) *ImageViewer{
	return &ImageViewer{
		ImageViewer:NewImageFlayweightFactory().GetImageFlyweight(filename)
	}
}